"""
Ollama API 服务 (services/ollama_service.py)

提供与 Ollama API 交互的功能，包括使用 deepseek-vision 模型进行图片识别和标签生成。
"""
import os
import requests
import base64
import logging
import json
import socket
from config.config import APP_CONFIG

logger = logging.getLogger(__name__)

# Ollama API 配置
OLLAMA_CONFIG = APP_CONFIG.get('OLLAMA_API', {})
USE_OLLAMA = OLLAMA_CONFIG.get('USE_OLLAMA', False)
OLLAMA_HOST = OLLAMA_CONFIG.get('HOST', 'http://localhost')
OLLAMA_PORT = OLLAMA_CONFIG.get('PORT', '11434')
OLLAMA_MODEL = OLLAMA_CONFIG.get('MODEL', 'deepseek-vision')
OLLAMA_API_URL = f"{OLLAMA_HOST}:{OLLAMA_PORT}/api/generate"

def check_ollama_service():
    """
    检查Ollama服务是否可用
    
    Returns:
        tuple: (True/False, 错误信息)
    """
    try:
        # 尝试解析主机名
        host = OLLAMA_HOST.replace('http://', '').replace('https://', '')
        # 尝试连接到端口
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.settimeout(2)  # 设置超时时间为2秒
        s.connect((host, int(OLLAMA_PORT)))
        s.close()
        return True, None
    except socket.error as e:
        return False, f"无法连接到Ollama服务: {str(e)}"
    except Exception as e:
        return False, f"检查Ollama服务时出错: {str(e)}"

def analyze_image_with_ollama(image_path):
    """
    使用 Ollama API 和 deepseek-vision 模型分析图片并生成中文标签。
    
    Args:
        image_path: 图片文件的完整路径
        
    Returns:
        tuple: (
            {
                'cn_tags': [中文标签列表]
            }, 
            None
        ) 或 (None, 错误信息)
    """
    if not os.path.exists(image_path):
        logger.error(f"图片文件不存在: {image_path}")
        return None, f"图片文件不存在: {image_path}"
    
    # 首先检查Ollama服务是否可用
    service_available, service_error = check_ollama_service()
    if not service_available:
        logger.error(service_error)
        return None, f"{service_error}。请确保已安装Ollama并运行了'ollama serve'命令，或在.env中将USE_OLLAMA设置为false使用OpenAI。"
    
    try:
        # 读取并编码图片为 base64
        with open(image_path, "rb") as image_file:
            base64_image = base64.b64encode(image_file.read()).decode('utf-8')
        
        # 构建 API 请求
        headers = {
            "Content-Type": "application/json"
        }
        
        # 使用 deepseek-vision 模型进行图片分析
        payload = {
            "model": OLLAMA_MODEL,
            "prompt": f"分析这张图片，从表情，情感，事物，场景维度进行分析。给出5个最相关的中文标签。以JSON格式返回，格式为：{{'cn_tags': ['标签1', '标签2', '标签3', '标签4', '标签5']}}",
            "images": [base64_image],
            "stream": False
        }
        
        # 发送请求
        try:
            response = requests.post(OLLAMA_API_URL, headers=headers, json=payload, timeout=30)
            response.raise_for_status()
        except requests.exceptions.HTTPError as e:
            if e.response.status_code == 404:
                # 检查是否是模型不存在
                try:
                    models_url = f"{OLLAMA_HOST}:{OLLAMA_PORT}/api/tags"
                    models_response = requests.get(models_url, timeout=5)
                    models_response.raise_for_status()
                    models_data = models_response.json()
                    available_models = [model.get("name") for model in models_data.get("models", [])]
                    
                    if OLLAMA_MODEL not in available_models:
                        return None, f"Ollama模型'{OLLAMA_MODEL}'不存在。请运行'ollama pull {OLLAMA_MODEL}'下载模型，或在.env中将USE_OLLAMA设置为false使用OpenAI。"
                except:
                    pass
            raise
        
        # 解析响应
        result = response.json()
        content = result.get('response', '')
        
        # 尝试从字符串中提取 JSON
        import re
        
        json_match = re.search(r'\{.*\}', content, re.DOTALL)
        if json_match:
            try:
                tags_data = json.loads(json_match.group(0))
                # 验证数据格式
                if 'cn_tags' in tags_data:
                    return tags_data, None
                else:
                    logger.error(f"API 返回的 JSON 数据格式不正确: {tags_data}")
                    return None, "API 返回的标签数据格式不正确"
            except json.JSONDecodeError as e:
                logger.error(f"解析 API 返回的 JSON 失败: {str(e)}")
                return None, f"解析 API 返回的 JSON 失败: {str(e)}"
        
        logger.error(f"无法从 API 响应中提取标签数据: {content}")
        return None, "无法从 API 响应中提取标签数据"
                
    except requests.exceptions.RequestException as e:
        logger.error(f"Ollama API 请求失败: {str(e)}")
        if "ConnectionRefusedError" in str(e):
            return None, f"无法连接到Ollama服务。请确保已启动Ollama并运行'ollama serve'命令，或在.env中将USE_OLLAMA设置为false使用OpenAI。"
        return None, f"Ollama API 请求失败: {str(e)}"
    except Exception as e:
        logger.error(f"图片分析过程中出错: {str(e)}")
        return None, f"图片分析过程中出错: {str(e)}" 